//
// nvGlutWidgets
//
//  Adaptor classes to integrate the nvWidgets UI library with the GLUT windowing
// toolkit. The adaptors convert native GLUT UI data to native nvWidgets data. All
// adaptor classes are implemented as in-line code in this header. The adaptor
// defaults to using the standard OpenGL paintor implementation.
//
// Author: Ignacio Castano, Samuel Gateau, Evan Hart
// Email: sdkfeedback@nvidia.com
//
// Copyright (c) NVIDIA Corporation. All rights reserved.
////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef NV_GLUT_WIDGETS_H
#define NV_GLUT_WIDGETS_H

#include "nvGLWidgets.h"
#include <GL/glut.h>

namespace nv {

	// Forward decls.
	class GlutManipulator;


	class GlutUIContext : public UIContext {

	protected:

		bool _ownPainter;

	public:

		//
		// Default UI constructor
		//
		//  Creates private OpenGL painter
		//////////////////////////////////////////////////////////////////
		GlutUIContext() :
		UIContext( *(new GLUIPainter()) ),
		_ownPainter(true) 
		{
		}

		//
		// Alternate UI constructor
		//
		//  Allows for overriding the standard painter
		//////////////////////////////////////////////////////////////////
		GlutUIContext(UIPainter& painter) : 
			UIContext( painter ),
			_ownPainter(false)
		{
		}

		//
		// UI  destructor
		//
		//  Destroy painter if it is private
		//////////////////////////////////////////////////////////////////
		~GlutUIContext() {
			if (_ownPainter) delete getPainter();
		}

		//
		// UI method for processing GLUT mouse button events
		//
		//  Call this method from the glutMouseFunc callback, the
		// modifier parameter maps to glutGetModifiers.
		//////////////////////////////////////////////////////////////////
		virtual void mouse(int button, int state, int modifier, int x, int y) { 
			int modifierMask = 0;

			if ( button == GLUT_LEFT_BUTTON) button = MouseButton_Left;
			else if ( button == GLUT_MIDDLE_BUTTON) button = MouseButton_Middle;
			else if ( button == GLUT_RIGHT_BUTTON) button = MouseButton_Right;

			if ( modifier & GLUT_ACTIVE_ALT) modifierMask |= ButtonFlags_Alt;
			if ( modifier & GLUT_ACTIVE_SHIFT) modifierMask |= ButtonFlags_Shift;
			if ( modifier & GLUT_ACTIVE_CTRL) modifierMask |= ButtonFlags_Ctrl;

			if ( state == GLUT_DOWN) state = 1; else state = 0;

			UIContext::mouse( button, state, modifierMask, x, y);
		}
		
		void mouse(int button, int state, int x, int y) {
			mouse(button, state, glutGetModifiers(), x, y);
		}

		//
		// UI method for processing key events
		//
		//  Call this method from the glutReshapeFunc callback
		//////////////////////////////////////////////////////////////////
		void specialKeyboard(int k, int x, int y) { UIContext::keyboard( translateKey(k), x, y); }

		//
		//  Translate non-ascii keys from GLUT to nvWidgets
		//////////////////////////////////////////////////////////////////
		unsigned char translateKey( int k )
		{
			switch (k)
			{
			case GLUT_KEY_F1 :
				return Key_F1;
			case GLUT_KEY_F2 :
				return Key_F2;
			case GLUT_KEY_F3 :
				return Key_F3;
			case GLUT_KEY_F4 :
				return Key_F4;
			case GLUT_KEY_F5 :
				return Key_F5;
			case GLUT_KEY_F6 :
				return Key_F6;
			case GLUT_KEY_F7 :
				return Key_F7;
			case GLUT_KEY_F8 :
				return Key_F8;
			case GLUT_KEY_F9 :
				return Key_F9;
			case GLUT_KEY_F10 :
				return Key_F10;
			case GLUT_KEY_F11 :
				return Key_F11;
			case GLUT_KEY_F12 :
				return Key_F12;
			case GLUT_KEY_LEFT :
				return Key_Left;
			case GLUT_KEY_UP :
				return Key_Up;
			case GLUT_KEY_RIGHT :
				return Key_Right;
			case GLUT_KEY_DOWN :
				return Key_Down;
			case GLUT_KEY_PAGE_UP :
				return Key_PageUp;
			case GLUT_KEY_PAGE_DOWN :
				return Key_PageDown;
			case GLUT_KEY_HOME :
				return Key_Home;
			case GLUT_KEY_END :
				return Key_End;
			case GLUT_KEY_INSERT :
				return Key_Insert;
			default:
				return 0;
			} 
		}

		
		NVSDKENTRY void updateManipulator(GlutManipulator & manipulator);

	private:

		void updateButtonState( const ButtonState & bs, GlutManipulator &manip, int button);

	};

};



#endif
